using System;
using System.Collections.Generic;
using System.Text;

using Mud.Common.Messages;
using Mud.Server.Physical;
using Mud.Common;

namespace Mud.Server.Client.Commands
{
    /// <summary>
    /// Command manager manages creature commands. It determines
    /// the order of command execution for all queued commands. It can also
    /// interupt the command beeing executed and start executing new one.
    /// </summary>
    public class CommandManager
    {


        private Creature _creature;
        private List<ControlerCommand> _futureCommands = new List<ControlerCommand>();
        private List<ControlerCommand> _pastCommands = new List<ControlerCommand>();

        /// <summary>
        /// Command that is currently executing
        /// </summary>
        public ControlerCommand CurrentCommand
        {
            get { return _currentCommand; }
        }
        private ControlerCommand _currentCommand;


        public IMessage QueueCommand(ControlerCommand command)
        {
            if (command.Type == ControlerCommandType.Instant) // instant command are resolved immediately
                return command.StartCommand();

            if (CurrentCommand != null && CurrentCommand.Executing)
            {
                if (CurrentCommand.CanBeInteruptedBy(command))
                {
                    Logger.Log(LogType.Debug, "CommandManager.QueueCommand", "Command {0} is executing but will be interupted by the command {1}.", CurrentCommand, command);
                    Logger.Log(LogType.Debug, "CommandManager.QueueCommand", "Command {0} is added at the start of the command queue.", command);
                    _futureCommands.Insert(0, command);
                    CurrentCommand.Interupt(command);
                }
                else
                {
                    Logger.Log(LogType.Debug, "CommandManager.QueueCommand", "Command {0} is executing, new command {1} will be added at the end of the command queue.", CurrentCommand, command);
                    _futureCommands.Add(command);
                }
            }
            else
            {
                _currentCommand = command;
                return StartCurrentCommand();
            }
            return MessageResponseOk.Instance;
        }

        private void CurrentCommand_CommandEnded(ControlerCommand command)
        {
            command.CommandEnded -= CurrentCommand_CommandEnded;
            _pastCommands.Add(command);
            if (_futureCommands.Count == 0)
                return;
            _currentCommand = _futureCommands[0];
            _futureCommands.RemoveAt(0);
            IMessage response = StartCurrentCommand();
            Logger.Log(LogType.Debug, "CommandManager.CommandEnded", "Command {0} was started non-interactively. Command response was {1}.", CurrentCommand, response);
        }

        private IMessage StartCurrentCommand()
        {
            CurrentCommand.CommandEnded += CurrentCommand_CommandEnded;
            return CurrentCommand.StartCommand();
        }

        public CommandManager(Creature creature)
        {
            if (creature == null)
                throw new ArgumentNullException("creature");
            _creature = creature;
        }

    }
}
